package gui;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.NetworkInterface;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

public class Logger {
	private static final int FLUSH_FREQUENCY_MILLIS = 5000;
	private static final String LOG_URL = "http://ozark.hendrix.edu/~burch/pbllog/log.php";
	private static final int[] LOG_IP_RANGE = { 209, 65, 56, 0, 21 };
	
	private static WriteThread thread;
	private static Object lock;
	private static ConcurrentLinkedQueue<String> buffer;
	private static boolean shouldFlush;
	
	static {
		buffer = new ConcurrentLinkedQueue<String>();
		lock = new Object();
		thread = new WriteThread();
		thread.start();
		shouldFlush = true;
	}
	
	public static void flush() {
		synchronized (lock) {
			shouldFlush = true;
			lock.notifyAll();
		}
	}
	
	public static void add(String s) {
		buffer.add(s);
		if (s.length() >= 1024) flush();
	}
	
	private static class WriteThread extends Thread {
		public void run() {
			// we're not going to attempt to send anything unless we establish
			// this host is on the Hendrix network.
			boolean isHendrix = isHostAtHendrix();
			
			while (true) {
				synchronized (lock) {
					if (!shouldFlush) {
						try {
							Thread.sleep(FLUSH_FREQUENCY_MILLIS);
						} catch (InterruptedException e) { }
					}
					shouldFlush = false;
				}
				
				if (!buffer.isEmpty()) {
					try {
						Thread.sleep(FLUSH_FREQUENCY_MILLIS);
					} catch (InterruptedException e) { }

					ArrayList<String> toSend = new ArrayList<String>();
					String toAdd = buffer.poll();
					while (toAdd != null) {
						toSend.add(toAdd);
						toAdd = buffer.poll();
					}
					
					if (isHendrix) {
						sendToLog(toSend);
					}
				}
			}
		}
		
		private static boolean isHostAtHendrix() {
			long hendrixMask = 0;
			int hendrixLength = 0;
			for (int b : LOG_IP_RANGE) {
				hendrixMask = 256 * hendrixMask + hendrixLength;
				hendrixLength = (b & 0xFF);
			}
			
			try {
				for (NetworkInterface iface : Collections.list(
							NetworkInterface.getNetworkInterfaces())) {
					for (InetAddress inet : Collections.list(
							iface.getInetAddresses())) {
						byte[] bytes = inet.getAddress();
						if (bytes.length == 4) {
							long ipAddress = 0;
							for (byte b : bytes) {
								ipAddress = 256 * ipAddress + (b & 0xFF);
							}
							ipAddress &= (-1) << (32 - hendrixLength);
							if (ipAddress == hendrixMask) {
								return true;
							}
						}
					}
				}
			} catch (Exception e) { }
			return false;
		}
		
		private static void sendToLog(List<String> toSend) {
			URLConnection connection = null;
			try {
				URL url = new URL(LOG_URL);
				connection = url.openConnection();
			} catch (MalformedURLException e) {
				return;
			} catch (IOException e) {
				return;
			}
			connection.setDoOutput(true);
		
			OutputStreamWriter out = null;
			try {
				out = new OutputStreamWriter(
                      connection.getOutputStream());
				for (String send : toSend) {
					out.write(send);
				}
				out.close();
			} catch (IOException e) {
				; // pass
			} finally {
				if (out != null) {
					try {
						out.close();
					} catch (IOException e) { }
				}
			}

			InputStreamReader in = null;
			try {
				in = new InputStreamReader(
						connection.getInputStream());
				char[] buf = new char[128];
				while (in.read(buf) >= 0) { }
			} catch (IOException e) {
				; // pass
			} finally {
				if (in != null) {
					try {
						in.close();
					} catch (IOException e) { }
				}
			}
		}
	}
}
